特定のAWS SSOユーザーのみ除外するSCPポリシー例
ちゃだいん(@chazuke4649)です。
AWS Organizations環境で予防的ガードレールとしてSCPを利用する際に、特定のAWS SSOユーザーを制限から除外したいケースがあります。
例えば「基本的にAWS SSOでユーザー管理を行うので、IAMユーザーを作成できないようにSCPでIAMユーザー作成を禁止したい。ただし、一部の管理者だけ除外したい。」といったパターンなどが挙げられます。
うまくいかない方法
これを行う際に、最初に考えたのはAWS SSOによってユーザーアカウントに自動生成されるIAMロール(SSOユーザーの実体)のARNを使うことでした。ARNを条件キーで指定するのはよくあるパターンです。
しかしながら、このパターンだと、ユーザーアカウントが複数ある場合、IAMロールも各ユーザーアカウントごとに作成されるため、指定するIAMロールのARNがどんどん増えていきます。例えばSSOユーザーTesyama Testaro
がOU配下の10ユーザーアカウントでSCPから除外したい場合、SCP自体は1つでOKかもしれませんが、条件キー部分にIAMロールのARNを10個記述することになります。管理が大変です。
さらに、よくよく考えてみると、このユーザーアカウントのIAMロールは正確には「アクセス権限セット」の実体です。IAMロールを指定してしまうとTesyama Testaro
ではない別のSSOユーザーが同じ「アクセス権限セット」を利用する場合、意図せずその別のSSOユーザーも除外されてしまうことになります。除外の対象はIAMロール(=アクセス権限セット)でなくSSOユーザーにすべきです。
この辺り、テキストだけではなんのこっちゃだと思うので、ぜひ以下ブログでAWS SSOの構成をつかんでください。
解決方法
ではどうすればSSOユーザーを指定できるのでしょうか?
答えは、AWS SSOIAMポリシーの条件キーでAWS SSOユーザーの UserId を指定することです。
要は飛び先のIAMロールでなく、元々SSO IDストア側で持つユーザーを一意に識別するIDを、IAM条件キーに使用できます。
上記ドキュメントに記載のサンプルがこちらです。本サンプルは「
{ "Version":"2012-10-17", "Statement":[ { "Effect":"Allow", "Principal": "*", "Action":["s3:GetObject","s3:GetObjectVersion"], "Resource":["arn:aws:s3:::mybucket/*"], "Condition": { "StringEquals": { "identitystore:UserId": [ "<UserId>" ] }, "Null": { "identitystore:UserId": "false" } } ] }
やってみる
前提条件
以下サービス・リソースは既に完了済みとなります。
- AWS Organizationsを作成し、ユーザーアカウントを発行
- AWS SSOを有効化
- SSOユーザーを作成
1.UserIdの取得
事前作成したSSOユーザーを Tesyama Testaro
とします。UserIdは各ユーザーの詳細画面で確認できるので、これをメモします。
2.SCPに設定
今回SCPとしては冒頭の事例のように「原則IAMユーザーの作成・削除などを禁止するが、特定のSSOユーザーのみ除外するSCP」を設定したいと思います。
先述の条件キーの記述と組み合わせると以下のようになります。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "DenyCreateUser", "Effect": "Deny", "Action": [ "iam:CreateUser", "iam:DeleteUser", "iam:CreateLoginProfile", "iam:CreateAccessKey" ], "Resource": [ "*" ], "Condition": { "StringNotEquals": { "identitystore:UserId": [ "95671e64ee-0654e2f1-85fe-xxxxxxxxxxxxxxxxxxxxxxx" ] }, "Null": { "identitystore:UserId": "false" } } } ] }
※UseId箇所はダミーです
こちらのSCPを対象のOUに設定します。
2021.9.2追記: 上記ポリシーだと一部不具合があったので、下記新しいポリシーの使用を推奨します。変更理由は後述します。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "DenyCreateUser", "Effect": "Deny", "Action": [ "iam:CreateUser", "iam:DeleteUser", "iam:CreateLoginProfile", "iam:CreateAccessKey" ], "Resource": [ "*" ], "Condition": { "StringNotEqualsIfExists": { "identitystore:UserId": [ "95671e64ee-0654e2f1-85fe-xxxxxxxxxxxxxxxxxxxxxxx" ] } } } ] }
※UseId箇所はダミーです
変更理由
元のポリシーだと、Conditionで判定しているキーidentitystore:UserId
をエンティティが保有してない場合(例:IAMユーザーなど)、結果はFalseとなり、Deny文が効かなくなります。
そこで今回 StringNotEqualsIfExists
に変更し、Null文
を削除しました。これによってキーがない場合はTrueになり、Deny文が効きます。
詳細は以下ブログをご参考ください。(該当箇所を以下引用してます)
キーが無いときに備えてどう対処するか? 条件キーの場合 指定したキーが無いときに 「trueとしたいか」、「falseとしたいか」 ポリシー設計段階で決めましょう。 「trueとしたい」 場合は IfExists を活用します。 (Nullを除く) 全ての条件演算子の末尾に付けることができます。 キーが存在しない場合に 条件要素は true として評価されます 。 「falseとしたい」 場合は Null 条件演算子 を使った条件を 明示的に追加 しましょう。
3.動作検証(UserIdを除外しない)
検証するために、先述のSCPと別に条件キーのない「有無を言わさずIAMユーザー作成を禁止するSCP」を作成しています。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "DenyCreateUser", "Effect": "Deny", "Action": [ "iam:CreateUser", "iam:DeleteUser", "iam:CreateLoginProfile", "iam:CreateAccessKey" ], "Resource": [ "*" ] } ] }
これをOUにアタッチし、先述のAdministratorAcess
権限のあるTesyama Testaro
SSOユーザーで対象ユーザーアカウントにアクセスします。
適当なIAMユーザーtempuser2
を作成しようとしたところ、以下の通りエラーが出ました。
4.動作検証(UserIdを除外する)
それでは次に、SCPDenyCreateIAMUser.json
をデタッチして、SCPDenyCreateIAMUserExceptAdmin.json
をアタッチします。
そして、再度同じようにIAMユーザーを作成しようと試みます。
すると以下のようにIAMユーザーを作成することができました。
終わりに
OrganizationsやAWS SSOを活用しLanding Zoneライクにマルチアカウント管理を行う場合、特定のSSOユーザーのみ除外したいSCPの記述方法についてご紹介しました。AWS SSO便利ですね。ガンガン使っていきましょう!
ちなみに、AWS SSO側にはSSOユーザー以外にSSOグループがあり、こちらには GroupId
があります。ただしGroupIdを条件キーで指定することは、IAMポリシーとしては未サポートです。(試したけどダメでした)
それではこの辺で。ちゃだいん(@chazuke4649)でした。